package com.tianji.learning.service.impl;

import cn.hutool.core.collection.CollStreamUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.tianji.api.client.user.UserClient;
import com.tianji.api.dto.user.UserDTO;
import com.tianji.common.domain.dto.PageDTO;
import com.tianji.common.exceptions.BizIllegalException;
import com.tianji.common.utils.AssertUtils;
import com.tianji.common.utils.BeanUtils;
import com.tianji.common.utils.UserContext;
import com.tianji.learning.domain.dto.ReplyDTO;
import com.tianji.learning.domain.po.InteractionQuestion;
import com.tianji.learning.domain.po.InteractionReply;
import com.tianji.learning.domain.query.ReplyPageQuery;
import com.tianji.learning.domain.vo.ReplyVO;
import com.tianji.learning.mapper.InteractionQuestionMapper;
import com.tianji.learning.mapper.InteractionReplyMapper;
import com.tianji.learning.service.IInteractionReplyService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 互动问题的回答或评论 服务实现类
 * </p>
 *
 * @author 东哥
 * @since 2025-10-25
 */
@Service
@RequiredArgsConstructor
@Slf4j
public class InteractionReplyServiceImpl extends ServiceImpl<InteractionReplyMapper, InteractionReply> implements IInteractionReplyService {
    private final InteractionQuestionMapper questionMapper;
    private final UserClient userClient;
    private final InteractionReplyMapper replyMapper;

    /**
     * 实战回复接口 5-1
     *
     * @param replyDTO
     */
    @Override
    @Transactional
    public void saveReply(ReplyDTO replyDTO) {
        //-1.内容审核
        //0.拷贝属性
        InteractionReply reply = BeanUtils.copyBean(replyDTO, InteractionReply.class);
        reply.setUserId(UserContext.getUser());
        //1. 判断是否是评论
        boolean isComment = replyDTO.getAnswerId() != null;
        if (isComment) {
            //1.1如果是评论，回答的评论数量+1
            Long answerId = reply.getAnswerId();
            boolean update = lambdaUpdate().eq(InteractionReply::getId, answerId).setSql("reply_times = reply_times + 1").update();
            AssertUtils.isTrue(update, "更新评论或回答数量+1 失败");
            //插入新的评论
            boolean save = save(reply);
            AssertUtils.isTrue(save, "保存评论或回答失败");
            return;
        }

        //2. 如果是回答，更新（问题最近一次回答Id、回答数量+1， [更新问题表中查看状态为未查看][如果是学生提交]）
        boolean save = save(reply);
        AssertUtils.isTrue(save, "保存回答失败");
        //更新问题表
//        InteractionQuestionMapper.
//                .lambdaUpdate()
//                //最近一次回答的id
//                .set(InteractionQuestion::getLatestAnswerId, reply.getId())
//                //回答数量+1
//                .setSql("answer_times = answer_times + 1")
//                //状态改为未查看(如果是学生）
//                .set(replyDTO.getIsStudent(), InteractionQuestion::getStatus, 0)
//                .eq(InteractionQuestion::getId, reply.getQuestionId())
//                .update();

        try {
            questionMapper.updateQuestioinData(replyDTO, reply);
        } catch (Exception e) {
            log.error("更新问题数据时发生异常", e);
            throw new RuntimeException(e);
        }
    }

    /**
     * 实战回复接口 5-2 分页查询回答或评论列表
     *
     * @param pageQuery
     */
    @Override
    @SuppressWarnings("unchecked")
    public PageDTO<ReplyVO> pageQuery(ReplyPageQuery pageQuery, Boolean isStudent) {
        //1.分页查询数据
//        1）、问题ID和回答ID至少需要一个
        Long answerId = pageQuery.getAnswerId();
        Long questionId = pageQuery.getQuestionId();
        if (questionId == null && answerId == null) {
            throw new BizIllegalException("参数错误，问题id和回答id不能同时为空");
        }

        //查询缺失的数据
        //是否是评论
        boolean isComment = answerId != null;

        Page<InteractionReply> pageResult = this.lambdaQuery()
                // 2）、如果查询回答分页列表，条件需要 问题ID
                .eq(!isComment, InteractionReply::getQuestionId, questionId)
                //3）、如果查询评论分页列表，条件需要 回答ID
                .eq(InteractionReply::getAnswerId, isComment ? answerId : 0L)
                //4）、如果是学生查询，需要过滤掉已隐藏的
                .eq(isStudent, InteractionReply::getHidden, false)
                //5）、先根据点赞数倒序排序，点赞数相同，再按照创建时间倒序排序
                .orderByDesc(InteractionReply::getLikedTimes)
                .orderByDesc(InteractionReply::getCreateTime)
                .page(Page.of(pageQuery.getPageNo(), pageQuery.getPageSize()));

        List<InteractionReply> records = pageResult.getRecords();
        //如果没有查到数据
        if (records == null || records.isEmpty()) {
            return PageDTO.empty(pageResult);
        }
        //获取提问者id 、回复的目标id、当前回答或评论id（统计点赞信息）
        Set<Long> userIds = new HashSet<>();
        Set<Long> answerIds = new HashSet<>();
        Set<Long> targetUserIds = new HashSet<>();
        Set<Long> targetReplyIds = new HashSet<>();

        records.forEach(reply -> {
            if (!isStudent || !reply.getAnonymity()) {
                userIds.add(reply.getUserId());
            }
            targetUserIds.add(reply.getTargetUserId());
            targetReplyIds.add(reply.getTargetReplyId());
            answerIds.add(reply.getId());
        });
//        如果有目标回复用户（评论分页），并且目标回复用户非匿名，需要设置用户昵称
        userIds.addAll(targetUserIds);


        //用户信息转Map
        Map<Long, UserDTO> userInfoMap;
        if (!userIds.isEmpty()) {
            List<UserDTO> userInfos = userClient.queryUserByIds(userIds);
            userInfoMap = CollStreamUtil.toIdentityMap(userInfos, UserDTO::getId);
        } else {
            userInfoMap = new HashMap<>();
        }
//        如果是用户端分页查询回答列表，需要分组查询每个回答下未被隐藏的评论数
        Map<Long, Integer> countReplyInfoMap;
        if(isStudent && !isComment){
//            List<Map<Long, Integer>> countReplyTimes = replyMapper.countReplyTimes();
//            countReplyInfoMap = countReplyTimes.stream().collect(Collectors.toMap(
//                    map -> map.get("id"), map -> map.get("num")
//            ));
            List<InteractionReply> numList = this.query()
                    .select("answer_id as id, count(1) as num")
                    .in("answer_id", answerIds)
                    .eq("hidden", false)
                    .groupBy("answer_id")
                    .list();
            countReplyInfoMap =  CollStreamUtil.toMap(numList, InteractionReply::getId, InteractionReply::getNum);
        } else {
            countReplyInfoMap = new HashMap<>();
        }

        //目标回复信息查询
        List<InteractionReply> targetReplyInfos = this.lambdaQuery()
                .eq(InteractionReply::getId, targetUserIds)
                .list();

        //目标回复信息转map
        Map<Long, InteractionReply> targetReplyInfoMap = CollStreamUtil.toIdentityMap(targetReplyInfos, InteractionReply::getId);

        //统计回答数
        List<ReplyVO> replyVOList = new ArrayList<>();
        records.forEach(r -> {
            ReplyVO v = BeanUtils.copyBean(r, ReplyVO.class);

            // 9）、如果查询回答分页列表，评论数量一列只显示 未被隐藏的评论数量
            if (isStudent && !isComment) {
                v.setReplyTimes(countReplyInfoMap.getOrDefault(r.getId(), 0).intValue());
            }
            //6）、如果是管理端或者非匿名情况需要查询提问者信息
            if (!isStudent || !r.getAnonymity()) {
                UserDTO userInfo = userInfoMap.get(r.getUserId());
                if (userInfo != null) {
                    //如果是评论，补充回答者昵称
                    v.setUserName(userInfo.getName());
                    //回答者头像
                    v.setUserIcon(userInfo.getIcon());
                    v.setUserType(userInfo.getType());
                }
            }
            // 7）、如果有目标回复用户（评论分页），并且目标回复用户非匿名，需要设置用户昵称
            //被评论用户的昵称
            Long targetReplyId = r.getTargetReplyId();
            if (targetReplyId != null) {
                InteractionReply interactionReply = targetReplyInfoMap.get(targetReplyId);
                if (interactionReply != null && !interactionReply.getAnonymity()) {
                    v.setTargetUserName(userInfoMap.get(interactionReply.getUserId()).getName());
                }
            }

            replyVOList.add(v);
        });
        // 8）、如果是管理端访问过某个问题的回答分页列表，将问题状态改为已查看
        if (!isStudent && questionId != null) {
            InteractionQuestion interactionQuestion = new InteractionQuestion();
            interactionQuestion.setId(questionId);
            interactionQuestion.setStatus(1);
            int result = questionMapper.updateById(interactionQuestion);
            if (result <= 0) {
                throw new RuntimeException("更新问题状态失败");
            }
        }
        //返回数据
        return PageDTO.of(pageResult, replyVOList);
    }

    @Override
    public void updateHidden(Long id, Boolean hidden) {
//        1、隐藏|显示指定【回答】或者【评论】
//        2）、如果是隐藏回答，需要隐藏下面的所有评论

        //判断是回答还是评论
        InteractionReply interactionReply = replyMapper.selectById(id);
        if (interactionReply == null) {
            throw new BizIllegalException("找不到回答或评论");
        }

        interactionReply.setHidden(hidden);
        int update = replyMapper.updateById(interactionReply);

        if (interactionReply.getAnswerId() == null || interactionReply.getAnswerId() == 0) {
            //是回答
            LambdaUpdateWrapper<InteractionReply> updateWrapper =
                    Wrappers.<InteractionReply>lambdaUpdate()
                            .set(InteractionReply::getHidden, hidden)
                            .eq(InteractionReply::getAnswerId, id);
            int update1 = replyMapper.update(null, updateWrapper);
            log.debug("更新{}条评论", update1);

        }
    }
}
